package com.siboxuetang.need.aspect;

import com.siboxuetang.need.util.SessionUtils;
import com.siboxuetang.need.util.WebUtils;
import com.siboxuetang.need.vo.LogEntity;
import com.siboxuetang.need.vo.NeedException;
import com.siboxuetang.need.vo.User;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;


import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

@Component
@Aspect
public class LogAopAction {


    @Pointcut("execution(public * com.siboxuetang.need.web.ctrl.*.*.*(..))")
    public void controllerAspect() {
    }

    @Around("controllerAspect()")
    public Object aroundController(ProceedingJoinPoint pjp) throws Throwable {
        LogEntity log = new LogEntity();
        //获取登录用户账户
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        String ip = WebUtils.getRemoteClientIp(request);
        log.setIp(ip);
        log.setApi(request.getRequestURL().append("?").append(request.getQueryString()).toString());
        //记录执行时间
        long start = System.currentTimeMillis();
        // 拦截的实体类，就是当前正在执行的controller
        Object target = pjp.getTarget();
        // 拦截的方法名称。当前正在执行的方法
        String methodName = pjp.getSignature().getName();

        // 拦截的放参数类型
        Signature sig = pjp.getSignature();
        MethodSignature msig = null;
        if (!(sig instanceof MethodSignature)) {
            throw new IllegalArgumentException("该注解只能用于方法");
        }
        msig = (MethodSignature) sig;
        Class[] parameterTypes = msig.getMethod().getParameterTypes();

        Object object = null;
        // 获得被拦截的方法
        Method method = null;
        try {
            method = target.getClass().getMethod(methodName, parameterTypes);
        } catch (NoSuchMethodException | SecurityException e1) {
            throw new NeedException(498, "拦截失败", e1);
        }
        if (null != method) {
            User user = SessionUtils.getSession(request, "_user", User.class);
            if (user == null) {
                log.setUserId("nobody");
            } else {
                log.setUserId(user.getId());
            }
        }
        try {
            object = pjp.proceed();
        } catch (NeedException e) {
            //记录并抛出
            if (e.getCause() != null) {
                log.setError(e.getCause().toString());
            }
            if (e.getMessage() != null) {
                log.setMsg(e.getMessage());
            }
            if (e.getStatus() != 0) {
                log.setStatus(String.valueOf(e.getStatus()));
            }
            throw e;
        } finally {
            long end = System.currentTimeMillis();
            log.setResponseTime(end - start);
            log.record(target.getClass());
//            servicesService.recordLog(log);
        }
        return object;
    }
}
